home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
pennmush.000
/
pennmush-1.50-p8-linux.tar
/
pennmush
/
speech.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-21
|
20KB
|
864 lines
/* speech.c */
#include "copyright.h"
/* Commands which involve speaking */
#include <ctype.h>
#include <string.h>
#include "config.h"
#include "externs.h"
#include "db.h"
#include "interface.h"
#include "match.h"
#include "attrib.h"
extern dbref speaker; /* from game.c */
#ifdef FULL_INVIS
const char *spname(thing)
dbref thing;
{
/* if FULL_INVIS is defined, dark objects and dark wizards will be
* Something and Someone, respectively.
*/
if (!Dark(thing))
return (Name(thing));
else {
if (Typeof(thing) != TYPE_PLAYER)
return ("Something");
else
return ("Someone");
}
}
#else
#define spname(x) (db[(x)].name)
#endif /* FULL_INVIS */
#ifdef NEVER
const char *reconstruct_message(arg1, arg2)
const char *arg1;
const char *arg2;
{
/* this function is a kludge for regenerating messages split by '='
* note that it messes up things like "Joe says, "foo == bar"".
*/
static char buf[BUFFER_LEN];
if (arg2 && *arg2) {
strcpy(buf, arg1);
strcat(buf, " = ");
strcat(buf, arg2);
return buf;
} else {
return arg1;
}
}
#endif /* NEVER */
void do_say(player, tbuf1)
dbref player;
const char *tbuf1;
{
dbref loc;
if ((loc = getloc(player)) == NOTHING)
return;
/* notify everybody */
notify_noecho(player, tprintf("You say, \"%s\"", tbuf1));
notify_except(db[loc].contents, player,
tprintf("%s says, \"%s\"", spname(player), tbuf1));
}
void do_oemit(player, arg1, arg2)
dbref player;
const char *arg1;
const char *arg2;
{
dbref who;
dbref loc;
char *temp;
void oemit_notify_except();
if ((temp = (char *)index(arg1, '/')) == NULL) {
if ((loc = getloc(player)) == NOTHING)
return;
init_match(player, arg1, NOTYPE);
match_neighbor();
match_me();
match_player();
match_absolute();
} else {
*temp++ = '\0';
/* first find the room */
init_match(player, arg1, NOTYPE);
match_everything();
if ((loc = noisy_match_result()) == NOTHING)
return;
/* then find the player */
init_match_remote(loc, temp, NOTYPE);
match_remote();
}
switch (who = match_result()) {
case NOTHING:
case AMBIGUOUS:
who = player;
default:
if (who != player)
notify_noecho(player, arg2);
oemit_notify_except(db[loc].contents, player, who, arg2);
}
}
void do_whisper(player, arg1, arg2)
dbref player;
const char *arg1;
const char *arg2;
{
dbref who;
int key;
const char *gap;
init_match(player, arg1, TYPE_PLAYER);
match_neighbor();
match_possession();
match_container();
match_me();
if (Wizard(player)) {
match_absolute();
match_player();
}
switch (who = match_result()) {
case NOTHING:
notify(player, "Whisper to whom?");
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
gap = " ";
switch (*arg2) {
case SEMI_POSE_TOKEN:
gap = "";
case POSE_TOKEN:
key = 1;
arg2 = arg2 + 1;
break;
default:
key = 2;
break;
}
switch (key) {
case 1:
notify(player, tprintf("%s senses, \"%s%s%s\"", db[who].name,
db[player].name, gap, arg2));
notify(who, tprintf("You sense: %s%s%s", db[player].name, gap, arg2));
break;
case 2:
notify(player,
tprintf("You whisper, \"%s\" to %s.", arg2, db[who].name));
notify(who,
tprintf("%s whispers, \"%s\"", db[player].name, arg2));
break;
}
break;
}
}
void do_pemit(player, arg1, arg2, silent)
dbref player;
const char *arg1;
const char *arg2;
int silent;
{
dbref who;
init_match(player, arg1, NOTYPE);
match_neighbor();
match_possession();
match_container();
match_me();
match_here();
match_player();
match_absolute();
switch (who = match_result()) {
case NOTHING:
notify(player, "I don't see that player here.");
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
if (Typeof(who) != TYPE_PLAYER && Typeof(who) != TYPE_THING) {
notify(player, "Only players and things can hear @pemits.");
break;
}
if ((player != who) &&
(Haven(who) ||
((Typeof(who) == TYPE_PLAYER) &&
!eval_boolexp(player, db[who].usekey, who, 0, USELOCK)))) {
notify(player,tprintf("I'm sorry, but %s wishes to be left alone now.",
db[who].name));
return;
}
if (!silent)
notify(player,
tprintf("You pemit \"%s\" to %s.", arg2, db[who].name));
if (Nospoof(who)) {
#ifdef PARANOID_NOSPOOF
notify(who, tprintf("[%s(#%d)->%s] %s", db[player].name, player,
db[who].name, arg2));
#else
notify(who,
tprintf("[%s->%s] %s", db[player].name, db[who].name, arg2));
#endif
} else {
notify(who,
tprintf("%s", arg2));
}
break;
}
}
void do_pose(player, tbuf1, space)
dbref player;
const char *tbuf1;
int space;
{
dbref loc;
if ((loc = getloc(player)) == NOTHING)
return;
/* notify everybody */
if(!space)
notify_except(db[loc].contents, NOTHING,
tprintf("%s %s", spname(player), tbuf1));
else
notify_except(db[loc].contents, NOTHING,
tprintf("%s%s", spname(player), tbuf1));
}
void do_wall(player, message, privs, key)
dbref player;
const char *message;
int privs;
int key;
{
/* privs is 0 for wizard wizwall, 1 for royalty-wizard wizwall,
* 2 is for general wall
*/
const char *gap, *prefix;
int mask;
/* command is only available to wizards and royalty */
if (!Hasprivs(player)) {
notify(player, "What makes you think someone wants to listen to you?");
return;
}
/* only @rwall is available to royalty */
if ((privs != 1) && !Wizard(player)) {
notify(player,
"Posing as a wizard could be hazardous to your health.");
return;
}
/* put together the message and figure out what type it is */
gap = " ";
switch(*message) {
case SAY_TOKEN:
key = 1;
message = message + 1;
break;
case SEMI_POSE_TOKEN:
gap = "";
case POSE_TOKEN:
key = 2;
message = message + 1;
break;
}
if (privs == 0) {
/* to wizards only */
mask = WIZARD;
prefix = "Broadcast";
}
#ifdef ROYALTY_FLAG
else if (privs == 1) {
/* to wizards and royalty */
mask = WIZARD | ROYALTY;
prefix = "Admin";
}
#endif /* ROYALTY_FLAG */
else {
/* to everyone */
mask = 0;
prefix = "Announcement";
}
/* broadcast the message */
switch(key) {
case 2:
raw_broadcast(mask, "%s: %s%s%s", prefix, db[player].name, gap,
message);
break;
case 3:
raw_broadcast(mask, "%s [%s]: %s", prefix, db[player].name, message);
break;
default:
raw_broadcast(mask, "%s: %s %s, \"%s\"", prefix, db[player].name,
((privs != 2) ? "says" : "shouts"), message);
}
/* log it if necessary */
if ((privs == 2) || (options.log_walls && (privs == 0))) {
switch (key) {
case 2:
do_log(LT_WIZ, player, NOTHING, "(MSG/%s) %s%s%s",
(privs == 0) ? "wiz" : "all", Name(player), gap, message);
break;
default:
do_log(LT_WIZ, player, NOTHING, "(MSG/%s) %s",
(privs == 0) ? "wiz" : "all", message);
break;
}
}
}
void do_page(player, arg1, arg2)
dbref player;
const char *arg1;
const char *arg2;
{
dbref target;
char *message;
const char *gap;
int key;
char tbuf[BUFFER_LEN];
if (!*arg1 && (!arg2 || !*arg2)) {
if (Typeof(player) == TYPE_PLAYER) {
if (db[player].parent == NOTHING) {
notify(player, "You haven't paged anyone since connecting.");
} else {
notify(player,
tprintf("You last paged %s.", db[db[player].parent].name));
}
} else
notify(player, "No record is being kept of your pages.");
return;
}
if (Haven(player))
notify(player, "You are set HAVEN and cannot receive pages.");
if (!arg2 || !*arg2) {
message = (char *) arg1;
if (Typeof(player) == TYPE_PLAYER)
target = db[player].parent;
else
target = NOTHING;
} else {
message = (char *) arg2;
if (!*arg1) {
if (Typeof(player) == TYPE_PLAYER)
target = db[player].parent;
else
target = NOTHING;
} else if ((target = lookup_player(arg1)) == NOTHING) {
if (!*arg2) {
if (Typeof(player) == TYPE_PLAYER)
target = db[player].parent;
else
target = NOTHING;
message = (char *) arg1;
} else {
target = short_page(arg1);
}
}
}
if (target == NOTHING) {
notify(player, "I can't find who you're trying to page.");
return;
} else if (target == AMBIGUOUS) {
notify(player, "I'm not sure who you want to page!");
return;
} else if (!(Toggles(target) & PLAYER_CONNECT) ||
(Dark(target) && Haven(target))) {
page_return(player, target, "Away", "AWAY",
"That player is not connected.");
return;
} else if (Haven(target)) {
page_return(player, target, "Haven", "HAVEN",
"That player is not accepting any pages.");
return;
} else if (!eval_boolexp(player, db[target].usekey,
target, 0, USELOCK)) {
page_return(player, target, "Haven", "HAVEN",
"That player is not accepting your pages.");
return;
} if (!payfor(player, PAGE_COST)) {
notify(player, tprintf("You don't have enough %s.", MONIES));
return;
}
if (Typeof(player) == TYPE_PLAYER)
db[player].parent = target;
gap = " ";
switch (*message) {
case SEMI_POSE_TOKEN:
gap = "";
case POSE_TOKEN:
key = 1;
message = message + 1;
break;
case NULL:
key = 2;
break;
default:
key = 3;
break;
}
/* this is a hack: truncate the message if it's going to overflow
* the tprintf buffer.
*/
if (strlen(message) > BUFFER_LEN - 32)
message[BUFFER_LEN - 32] = '\0';
switch (key) {
case 1:
sprintf(tbuf, "From afar, %s%s%s", db[player].name, gap, message);
notify(player, tprintf("Long distance to %s: %s%s%s", db[target].name,
db[player].name, gap, message));
break;
case 2:
sprintf(tbuf, "You sense that %s is looking for you in %s",
db[player].name, db[getloc(player)].name);
notify(player, tprintf("You have notified %s of your location.",
db[target].name));
break;
case 3:
sprintf(tbuf, "%s pages: %s", db[player].name, message);
notify(player, tprintf("You paged %s with '%s'.", db[target].name,
message));
break;
}
if (Typeof(player) != TYPE_PLAYER && Nospoof(target))
notify(target, tprintf("[#%d] %s", player, tbuf));
else
notify(target, tbuf);
page_return(player, target, "Idle", "IDLE", NULL);
return;
}
void esnotify(player, msg, sender)
dbref player;
const char *msg;
dbref sender;
{
if (player < 0 || player >= db_top) return;
if (Nospoof(player)) {
#ifdef PARANOID_NOSPOOF
notify_noecho(player,
tprintf("[%s(#%d)] %s", spname(sender), sender, msg));
#else
notify_noecho(player, tprintf("[%s:] %s", spname(sender), msg));
#endif
} else {
notify_noecho(player, msg);
}
}
int filter_found(thing, msg, flag)
dbref thing;
const char *msg;
int flag; /* 0 for @filter, 1 for @infilter */
{
/* check to see if the message matches the filter pattern on thing */
char *filter;
ATTR *a;
char *p;
char *temp; /* need this so we don't leak memory
* by failing to free the storage
* allocated by safe_uncompress
*/
int i;
int matched = 0;
if (!flag)
a = atr_get(thing, "FILTER");
else
a = atr_get(thing, "INFILTER");
if (!a)
return matched;
filter = safe_uncompress(a->value);
temp = filter;
for (i = 0; (i < MAX_ARG) && !matched; i++) {
p = parse_to(&filter, ',', 0);
if (p)
matched = wild_match(p, msg);
}
free(temp);
return matched;
}
void propagate_sound(thing, msg)
dbref thing;
const char *msg;
{
/* pass a message on, for AUDIBLE, prepending a prefix, unless the
* message matches a filter pattern.
*/
char *prefix, *bp;
char tbuf1[BUFFER_LEN];
ATTR *a;
dbref player;
dbref loc = db[thing].location;
if (!GoodObject(loc))
return;
/* check to see that filter doesn't suppress message */
if (filter_found(thing, msg, 0))
return;
/* figure out the prefix */
a = atr_get(thing, "PREFIX");
if (!a) {
prefix = (char *) malloc(BUFFER_LEN + 1);
if (Typeof(thing) == TYPE_EXIT)
sprintf(prefix, "From %s,", Name(Exits(thing)));
else
sprintf(prefix, "From %s,", Name(thing));
} else {
strcpy(tbuf1, uncompress(a->value));
prefix = exec(thing, speaker, EV_STRIP | EV_FCHECK, tbuf1);
}
bp = tbuf1;
safe_str(prefix, tbuf1, &bp);
safe_chr(' ', tbuf1, &bp);
safe_str(msg, tbuf1, &bp);
*bp = '\0';
/* Exits pass the message on to things in the next room.
* Objects pass the message on to the things outside.
* Don't tell yourself your own message.
*/
if (Typeof(thing) == TYPE_EXIT) {
DOLIST(player, db[loc].contents)
notify(player, tbuf1);
} else {
DOLIST(player, db[loc].contents) {
if (player != thing)
notify(player, tbuf1);
}
}
free(prefix);
}
void notify_except(first, exception, msg)
dbref first;
dbref exception;
const char *msg;
{
dbref loc = db[first].location;
dbref e;
char tbuf1[BUFFER_LEN];
if(first < 0 || first >= db_top)
return;
if (loc != exception)
notify_noecho(loc, msg);
DOLIST(first, first) {
if (first != exception) {
notify_noecho(first, msg);
}
}
/* now do AUDIBLE stuff */
if (Audible(loc)) {
if (Typeof(loc) == TYPE_ROOM) {
/* the strcpy is necessary to prevent choking in propagate_sound
* when msg is an array of char and not a char * in the calling
* function. Yes, this is ugly and stupid. It works. Kinda.
*/
strcpy(tbuf1, msg);
DOLIST(e, db[loc].exits) {
if (Audible(e))
propagate_sound(e, tbuf1);
}
} else if (loc != exception) {
strcpy(tbuf1, msg);
propagate_sound(loc, tbuf1);
}
}
}
void emit_notify_except(first, exception, msg)
dbref first;
dbref exception;
const char *msg;
{
dbref loc = db[first].location;
dbref e;
char tbuf1[BUFFER_LEN];
if(first < 0 || first >= db_top)
return;
if (loc != exception)
esnotify(loc, msg, exception);
DOLIST(first, first) {
if (first != exception) {
esnotify(first, msg, exception);
}
}
/* do AUDIBLE stuff */
if (Audible(loc)) {
if (Typeof(loc) == TYPE_ROOM) {
/* see notify_except for explanation of why strcpy is needed */
strcpy(tbuf1, msg);
DOLIST(e, db[loc].exits) {
if (Audible(e))
propagate_sound(e, tbuf1);
}
} else if (loc != exception) {
strcpy(tbuf1, msg);
propagate_sound(loc, tbuf1);
}
}
}
void notify_except2(first, exc1, exc2, msg)
dbref first;
dbref exc1;
dbref exc2;
const char *msg;
{
dbref loc = db[first].location;
dbref e;
char tbuf1[BUFFER_LEN];
if(first < 0 || first >= db_top)
return;
if ((loc != exc1) && (loc != exc2))
notify_noecho(loc, msg);
DOLIST(first, first) {
if (first != exc1 && first != exc2) {
notify_noecho(first, msg);
}
}
/* now do AUDIBLE stuff */
if (Audible(loc)) {
if (Typeof(loc) == TYPE_ROOM) {
/* see notify_except for explanation of why strcpy is necessary */
strcpy(tbuf1, msg);
DOLIST(e, db[loc].exits) {
if (Audible(e))
propagate_sound(e, tbuf1);
}
} else if ((loc != exc1) && (loc != exc2)) {
strcpy(tbuf1, msg);
propagate_sound(loc, tbuf1);
}
}
}
void oemit_notify_except(first, exc1, exc2, msg)
dbref first;
dbref exc1;
dbref exc2;
const char *msg;
{
dbref loc = db[first].location;
dbref e;
char tbuf1[BUFFER_LEN];
if(first < 0 || first >= db_top)
return;
if ((loc != exc1) && (loc != exc2))
esnotify(loc, msg, exc1);
DOLIST(first, first) {
if (first != exc1 && first != exc2) {
esnotify(first, msg, exc1);
}
}
/* do AUDIBLE stuff */
if (Audible(loc)) {
if (Typeof(loc) == TYPE_ROOM) {
/* see notify_except for explanation of why strcpy is needed */
strcpy(tbuf1, msg);
DOLIST(e, db[loc].exits) {
if (Audible(e))
propagate_sound(e, tbuf1);
}
} else {
strcpy(tbuf1, msg);
propagate_sound(loc, tbuf1);
}
}
}
void do_think(player, message)
dbref player;
const char *message;
{
/* privately tell yourself a message */
/* notify the player only, with no special fanfare */
notify(player, tprintf("%s", message));
}
void do_emit(player, tbuf1)
dbref player;
const char *tbuf1;
{
dbref loc;
if ((loc = getloc(player)) == NOTHING)
return;
/* notify everybody */
notify_noecho(player, tprintf("%s", tbuf1));
emit_notify_except(db[loc].contents, player, tbuf1);
}
void do_remit(player, arg1, arg2)
dbref player;
const char *arg1;
const char *arg2;
{
dbref room;
const char *rmno;
init_match(player, arg1, NOTYPE);
match_here();
match_absolute();
match_neighbor();
match_me();
match_player();
match_exit();
switch (room = match_result()) {
case NOTHING:
case AMBIGUOUS:
notify(player, "I can't find that.");
break;
default:
if (Typeof(room) == TYPE_EXIT) {
notify(player, "There can't be anything in that!");
break;
}
if ((Typeof(room) == TYPE_PLAYER) &&
(Haven(room) ||
!eval_boolexp(player, db[room].usekey, room, 0, USELOCK))) {
notify(player,tprintf("I'm sorry, but %s wishes to be left alone now.",
db[room].name));
break;
}
rmno = unparse_object(player, room);
notify(player,
tprintf("You remit, \"%s\" in %s", arg2, rmno));
oemit_notify_except(db[room].contents, player, room, arg2);
}
}
void do_lemit(player, tbuf1)
dbref player;
const char *tbuf1;
{
/* give a message to the "absolute" location of an object */
dbref room;
int rec = 0;
/* only players and things may use this command */
if (!Mobile(player))
return;
/* prevent infinite loop if player is inside himself */
if (((room = db[player].location) == player) || !GoodObject(room)) {
notify(player, "Invalid container object.");
fprintf(stderr, "** BAD CONTAINER ** #%d is inside #%d.\n",
player, room);
return;
}
while ((Typeof(room) != TYPE_ROOM) && (rec < 15)) {
room = db[room].location;
rec++;
}
if (rec > 15) {
notify(player, "Too many containers.");
return;
} else {
notify(player, tprintf("You lemit: \"%s\"", tbuf1));
oemit_notify_except(db[room].contents, player, room, tbuf1);
}
}
void do_zemit(player, arg1, arg2)
dbref player;
const char *arg1;
const char *arg2;
{
const char *where;
dbref zone;
dbref room;
init_match(player, arg1, NOTYPE);
match_absolute();
switch (zone = match_result()) {
case NOTHING:
case AMBIGUOUS:
notify(player, "Invalid zone.");
return;
default:
if (!controls(player, zone)) {
notify(player, "Permission denied.");
return;
}
/* this command is computationally expensive */
if (!payfor(player, FIND_COST)) {
notify(player, "Sorry, you don't have enough money to do that.");
return;
}
where = unparse_object(player, zone);
notify(player,
tprintf("You zemit, \"%s\" in zone %s", arg2, where));
/* walk the database, giving the message to the contents of all
* rooms that are zoned to the specified zone.
*/
for (room = 0; room < db_top; room++)
if ((getzone(room) == zone) && (Typeof(room) == TYPE_ROOM))
oemit_notify_except(db[room].contents, player, room, arg2);
}
}